package org.example.bobofish.user.infrastructure.persistence.repository;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.example.bobofish.user.application.facade.entity.LockUserRightsRequest;
import org.example.bobofish.user.domain.model.UserRightsInfoModel;
import org.example.bobofish.user.domain.repository.UserRightsRepository;
import org.example.bobofish.user.infrastructure.persistence.dao.UserRightsInfoDao;
import org.example.bobofish.user.infrastructure.persistence.entity.UserRightsInfo;
import org.example.bobofish.user.infrastructure.persistence.map.UserRightsInfoMapper;
import org.example.bobofish.user.common.util.CacheUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author : yuxiong
 * @date : 2025/6/17
 */
@Repository
public class UserRightsRepositoryImpl implements UserRightsRepository {

    @Autowired
    UserRightsInfoDao userRightsInfoDao;

    @Autowired
    private CacheUtil<List<UserRightsInfo>> cacheUtil;

    /**
     * 缓存穿透：空结果缓存+过期时间
     * 缓存雪崩：随机缓存时间
     * 缓解击穿：加锁，热点数据一次只允许一个请求访问
     * 1.SpringBoot组件在容器中都是单例的，单体应用：使用本地锁synchronized加锁 ok
     * 2.分布式锁TODO
     *
     * @param userId
     * @return
     */
    @Override
    public List<UserRightsInfoModel> getUserRightsList(String userId) {

        List<UserRightsInfo> userRightsInfoList;

        synchronized (this) {
            String key = "selectListById_" + userId;
            String cachedData = cacheUtil.getCachedData(key);
            userRightsInfoList = JSON.parseObject(cachedData, new TypeReference<List<UserRightsInfo>>() {
            });
            System.out.println("cache list:" + userRightsInfoList);
            if (cachedData == null) {
                userRightsInfoList = userRightsInfoDao.selectListById(userId);
                cacheUtil.cacheDataExpire(key, userRightsInfoList, 1, TimeUnit.MINUTES);
                System.out.println("db list:" + userRightsInfoList);
            }
        }

        return UserRightsInfoMapper.INSTANCE.convert(userRightsInfoList);
    }

    @Override
    public void operateRights(LockUserRightsRequest userRightsRequest) {
        List<UserRightsInfoModel> userRightsList = getUserRightsList(userRightsRequest.getUserId());
        userRightsList.stream().filter(x -> userRightsRequest.getRightNo().equalsIgnoreCase(x.getRightNo()))
                .findFirst()
                .ifPresent(x -> userRightsInfoDao.updateById(UserRightsInfoMapper.INSTANCE.convertReverse(x)));
    }
}
